package cn.wolfcode.business.service.impl;

import cn.wolfcode.business.domain.BusAppointment;
import cn.wolfcode.business.domain.BusStatement;
import cn.wolfcode.business.mapper.BusStatementMapper;
import cn.wolfcode.business.service.IBusAppointmentService;
import cn.wolfcode.business.service.IBusStatementService;
import cn.wolfcode.business.utils.DateUtil;
import cn.wolfcode.business.utils.RegexUtils;
import cn.wolfcode.business.utils.VehiclePlateNoUtil;
import cn.wolfcode.common.utils.DateUtils;
import cn.wolfcode.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 结算单Service业务层处理
 * 
 * @author wolfcode
 * @date 2025-08-21
 */
@Service
public class BusStatementServiceImpl implements IBusStatementService 
{
    @Autowired
    private BusStatementMapper busStatementMapper;
    @Autowired
    private IBusAppointmentService appointmentService;

    /**
     * 查询结算单
     * 
     * @param id 结算单主键
     * @return 结算单
     */
    @Override
    public BusStatement selectBusStatementById(Long id)
    {
        // 设置只查询有效结算单
        return busStatementMapper.selectBusStatementById(id);
    }

    /**
     * 查询结算单列表
     * 
     * @param busStatement 结算单
     * @return 结算单
     */
    @Override
    public List<BusStatement> selectBusStatementList(BusStatement busStatement) throws ParseException {
        // 获取到我们的额外参数
        String endDate = (String) busStatement.getParams().get("endActualArrivalTime");
        if(StringUtils.isNotEmpty(endDate)){
            // 将 String 类型转换为 Date 类型
            Date date = DateUtil.parseDate(endDate,"yyyy-MM-dd");
            // 更改时间 + 1 分  -1 秒
            Date addModifyTime = DateUtil.getModifyTime(date, Calendar.DAY_OF_YEAR, 1);
            Date subModifyTime = DateUtil.getModifyTime(addModifyTime, Calendar.SECOND, -1);
            // 将 Date 类型转换为 String
            String endTime = DateUtil.Date2String(subModifyTime, "yyyy-MM-dd HH:mm:ss");
            busStatement.getParams().put("endActualArrivalTime", endTime);
        }
        // 设置只查询有效结算单
        busStatement.setIsDelete(BusStatement.IS_NOT_DELETE);
        return busStatementMapper.selectBusStatementList(busStatement);
    }

    /**
     * 新增结算单
     * 
     * @param busStatement 结算单
     * @return 结果
     */
    @Override
    public int insertBusStatement(BusStatement busStatement)
    {
        //  1. 参数合理化验证。
        // Assert.isNull(busAppointment,"非法参数");   // 断言
        if(busStatement == null){
            throw new RuntimeException("非法参数");
        }
        // 前端的验证后端都要再次验证（必须不能为 Null 的参数）
        if(busStatement.getCustomerName() == null || busStatement.getCustomerPhone() == null
            || busStatement.getActualArrivalTime() == null || busStatement.getLicensePlate() == null
            || busStatement.getCarSeries() == null || busStatement.getServiceType() == null){
            throw new RuntimeException("非法参数");
        }
        // 	2. 手机号码合理化验证。（格式）
        if(!RegexUtils.isPhoneLegal(busStatement.getCustomerPhone())){
            throw new RuntimeException("手机号码格式有误");
        }
        // 	3. 车牌号码合理化校验。
        VehiclePlateNoUtil.VehiclePlateNoEnum vehiclePlateNo =
                VehiclePlateNoUtil.getVehiclePlateNo(busStatement.getLicensePlate());
        if(vehiclePlateNo == null){
            throw new RuntimeException("车牌号码格式有误");
        }
        // 	4. 时间合法性校验（预约时间必须大于当前系统时间）。
        Date nowDate = DateUtils.getNowDate();
        if(!(nowDate.after(busStatement.getActualArrivalTime()))){
            throw new RuntimeException("到店时间异常");
        }
        // 5.安全性设置
        busStatement.setStatus(BusStatement.STATUS_CONSUME);
        busStatement.setIsDelete(BusStatement.IS_NOT_DELETE);
        busStatement.setCreateTime(DateUtils.getNowDate());
        return busStatementMapper.insertBusStatement(busStatement);
    }

    /**
     * 修改结算单
     * 
     * @param busStatement 结算单
     * @return 结果
     */
    @Override
    public int updateBusStatement(BusStatement busStatement)
    {
        //  1. 参数合理化验证。
        // Assert.isNull(busAppointment,"非法参数");   // 断言
        if(busStatement == null){
            throw new RuntimeException("非法参数");
        }
        // 前端的验证后端都要再次验证（必须不能为 Null 的参数）
        if(busStatement.getCustomerName() == null || busStatement.getCustomerPhone() == null
                || busStatement.getActualArrivalTime() == null || busStatement.getLicensePlate() == null
                || busStatement.getCarSeries() == null || busStatement.getServiceType() == null){
            throw new RuntimeException("非法参数");
        }
        // 	2. 手机号码合理化验证。（格式）
        if(!RegexUtils.isPhoneLegal(busStatement.getCustomerPhone())){
            throw new RuntimeException("手机号码格式有误");
        }
        // 	3. 车牌号码合理化校验。
        VehiclePlateNoUtil.VehiclePlateNoEnum vehiclePlateNo =
                VehiclePlateNoUtil.getVehiclePlateNo(busStatement.getLicensePlate());
        if(vehiclePlateNo == null){
            throw new RuntimeException("车牌号码格式有误");
        }
        // 	4. 时间合法性校验（预约时间必须大于当前系统时间）。
        Date nowDate = DateUtils.getNowDate();
        if(!(nowDate.after(busStatement.getActualArrivalTime()))){
            throw new RuntimeException("到店时间异常");
        }
        // 状态必须是消费中才可以进行编辑操作
        BusStatement oldObj = this.selectBusStatementById(busStatement.getId());
        if(oldObj == null || !oldObj.getStatus().equals(busStatement.getStatus())){
            throw new RuntimeException("非法参数");
        }
        if(BusStatement.STATUS_PAID.equals(busStatement.getStatus())){
            throw new RuntimeException("已支付的结算单禁止编辑");
        }
        // 编辑的必须是有效用户
        if(!oldObj.getIsDelete().equals(busStatement.getIsDelete())){
            throw new RuntimeException("非法参数");
        }
        if(BusStatement.IS_DELETE.equals(busStatement.getIsDelete())){
            throw new RuntimeException("已删除用户无法进行编辑操作");
        }
        return busStatementMapper.updateBusStatement(busStatement);
    }

    /**
     * 批量删除结算单
     * 
     * @param ids 需要删除的结算单主键
     * @return 结果
     */
    @Override
    public int deleteBusStatementByIds(Long[] ids)
    {
        // 参数验证
        if(ids == null || ids.length == 0){
            throw new RuntimeException("非法参数");
        }
        Long id = ids[0];
        BusStatement statement = this.selectBusStatementById(id);
        if(statement == null){
            throw new RuntimeException("非法参数");
        }
        // 判定状态必须是消费中才可以进行（软）删除操作
        if(BusStatement.STATUS_PAID.equals(statement.getStatus())){
            throw new RuntimeException("已支付的结算单不能进行删除操作");
        }
        // 判断是否存在预约单 ID （是否为预约用户），若存在则需要将对应的预约单状态回退到已到店
        if(statement.getAppointmentId() != null){
            // 是预约用户，需要回退状态
            appointmentService.updateStatus(statement.getAppointmentId(), BusAppointment.STATUS_ARRIVED);
        }
        return busStatementMapper.deleteBusStatementByIds(id,BusStatement.IS_DELETE);
    }

    /**
     * 删除结算单信息
     * 
     * @param id 结算单主键
     * @return 结果
     */
    @Override
    public int deleteBusStatementById(Long id)
    {
        return busStatementMapper.deleteBusStatementById(id);
    }

    /**
     * 根据 statementId 更新结算单 总金额 总数量 折扣价
     * @param statementId 结算单 id
     * @param totalAmount 总金额
     * @param totalQuantity 总数量
     * @param discountAmount 折扣价
     * @return 更新结果
     */
    @Override
    public int updateAmount(Long statementId, BigDecimal totalAmount, BigDecimal totalQuantity, BigDecimal discountAmount) {
        return busStatementMapper.updateAmount(statementId, totalAmount, totalQuantity, discountAmount);
    }

    /**
     * 根据结算单ID，更新结算单状态、收款人、收款时间
     * @param statementId 结算单D
     * @param payId 收款人ID
     * @param date 收款时间
     * @param statusPaid 结算单状态
     */
    @Override
    public int updatePayStatusById(Long statementId, Long payId, Date date, Integer statusPaid) {
        return busStatementMapper.updatePayStatusById(statementId, payId, date, statusPaid);
    }

    /**
     * 根据预约单 ID 查询对应的结算单对象
     * @param id 预约单ID
     * @return  结算单对象
     */
    @Override
    public BusStatement selectStatementByAppointmentId(Long id) {

        return busStatementMapper.selectStatementByAppointmentId(id);
    }

    /**
     * 根据结算单 ID 修改结算单是否被删除的状态
     * @param id 结算单ID
     * @param isNotDelete 是否被删除的状态
     */
    @Override
    public void changeIsDelete(Long id, Integer isNotDelete) {
        busStatementMapper.changeIsDelete(id,isNotDelete);
    }
}
